package cloud.seri.auth.domain

import cloud.seri.auth.config.Constants
import com.fasterxml.jackson.annotation.JsonIgnore
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.index.Indexed
import org.springframework.data.mongodb.core.mapping.DBRef
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.core.mapping.Field
import java.io.Serializable
import java.time.Instant
import java.time.LocalDate
import java.util.*
import javax.persistence.Entity
import javax.validation.constraints.Email
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size

/**
 * A user.
 */
@Document(collection = "seri_user")
@Entity
class User @JvmOverloads constructor(

    @Id
    var id: String? = null,

    login: String? = null,

    @JsonIgnore
    @field:NotNull
    @field:Size(min = 60, max = 60)
    var password: String? = null,

    @field:Size(max = 50)
    @Field("user_name")
    var userName: String? = null,

    @field:Size(max = 50)
    @Field("real_name")
    var realName: String? = null,

    var birthday: LocalDate? = null,

    var phone: String? = null,

    var sex: Int? = null,

    @field:Email
    @field:Size(min = 5, max = 254)
    @Indexed
    var email: String? = null,

    var activated: Boolean = false,

    @field:Size(min = 2, max = 6)
    @Field("lang_key")
    var langKey: String? = null,

    @field:Size(max = 256)
    @Field("image_url")
    var imageUrl: String? = null,

    @field:Size(max = 20)
    @Field("activation_key")
    @JsonIgnore
    var activationKey: String? = null,

    @field:Size(max = 20)
    @Field("reset_key")
    @JsonIgnore
    var resetKey: String? = null,

    @Field("reset_date")
    var resetDate: Instant? = null,

    var status: Int? = 0,

    @JsonIgnore
    @DBRef(lazy = true)
    var roles: MutableSet<Role> = mutableSetOf(),

    @DBRef
    var dept: Dept? = null,

    createdBy: String? = null,
    createdDate: Instant? = Instant.now(),
    lastModifiedBy: String? = null,
    lastModifiedDate: Instant? = Instant.now()
) : AbstractAuditingEntity(createdBy, createdDate, lastModifiedBy, lastModifiedDate), Serializable
{

    @NotNull
    @field:Pattern(regexp = Constants.LOGIN_REGEX)
    @field:Size(min = 1, max = 50)
    @Indexed
    var login: String? = login
        set(value)
        {
            // Lowercase the login before saving it in database
            field = value?.toLowerCase(Locale.ENGLISH)
        }

    override fun equals(other: Any?): Boolean
    {
        if (this === other) return true
        if (other !is User) return false
        if (other.id == null || id == null) return false

        return Objects.equals(id, other.id)
    }

    override fun hashCode(): Int
    {
        return 31
    }

    override fun toString(): String
    {
        return "User{" +
            "login='" + login + '\'' +
            ", firstName='" + userName + '\'' +
            ", lastName='" + realName + '\'' +
            ", email='" + email + '\'' +
            ", imageUrl='" + imageUrl + '\'' +
            ", activated='" + activated + '\'' +
            ", langKey='" + langKey + '\'' +
            ", activationKey='" + activationKey + '\'' +
            "}"
    }

    companion object
    {
        private const val serialVersionUID = 1L
    }
}
